fix: default encoding_error_handler to replace in stdio_client for UTF-8 resilience#2553
Open
Maanik23 wants to merge 1 commit intomodelcontextprotocol:mainfrom
Open
Conversation
…F-8 resilience The stdio_client transport previously defaulted to encoding_error_handler= strict, causing the transport to crash when the child process emits invalid UTF-8 bytes. This is asymmetric with the server-side fix in PR modelcontextprotocol#2302, which already uses errors=replace for stdio_server. Changes: - Default StdioServerParameters.encoding_error_handler to replace - Invalid bytes are now substituted with U+FFFD and the resulting line fails JSON validation, surfacing as an in-stream Exception - The transport stays alive for subsequent valid messages - Changed logger.exception to logger.warning for parse failures (avoids noisy tracebacks for expected validation errors) - Removed pragma: no cover from the now-reachable exception handling path Add regression test that spawns a child emitting invalid UTF-8 followed by a valid JSON-RPC message, asserting both are delivered correctly. Fixes modelcontextprotocol#2454
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #2454
Summary
The
stdio_clienttransport crashes when the spawned child process writes invalid UTF-8 bytes to stdout. The transport decodes child stdout withencoding_error_handler="strict"by default, so malformed bytes raise duringTextReceiveStreamiteration. That exception escapes the decoding loop and brings down the transport task group instead of surfacing the bad line as an in-stream parse error.Asymmetry with server side
The SDK already hardened the server side for the analogous case in PR #2302 (
fix: handle non-UTF-8 bytes in stdio server stdin). That change explicitly preferred:The client side was still using
"strict", creating an inconsistency.Changes
src/mcp/client/stdio.pyStdioServerParameters.encoding_error_handlerdefault from"strict"to"replace"logger.exceptiontologger.warningfor JSON parse failures (avoids noisy full tracebacks for expected validation errors on malformed input)# pragma: no coverfrom the now-reachable exception handling pathtests/client/test_stdio.pytest_stdio_client_invalid_utf8_resilience— spawns a child that writes\xff\xfe\n(invalid UTF-8) followed by a valid JSON-RPC message, then asserts:Exception(JSON validation failure on the U+FFFD-replaced line)SessionMessagewith the expected payloadBackward compatibility
encoding_error_handler="strict"retain the old behaviorExceptionitems (the type signature isMemoryObjectReceiveStream[SessionMessage | Exception])